package com.xyzwps.orm.gsql.repository

import com.xyzwps.orm.exception.TagDuplicateException
import com.xyzwps.orm.model.Tag
import com.xyzwps.orm.repository.TagRepository
import com.xyzwps.orm.util.ExceptionUtils
import groovy.sql.Sql

import java.sql.SQLIntegrityConstraintViolationException

class GsqlTagRepository implements TagRepository {

    private final Sql sql

    GsqlTagRepository(Sql sql) {
        this.sql = Objects.requireNonNull(sql)
    }

    @Override
    int insert(Tag tag) {
        try {
            def result = sql.executeInsert "insert into tag set tag_name = $tag.tagName, user_id = $tag.userId"
            return result.first().first() as int
        } catch (ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.tagName)
            } else {
                throw new IllegalStateException(ex)
            }
        }
    }

    @Override
    void update(Tag tag) {
        try {
            def params = [tag.userId, tag.tagName, tag.tagId]
            sql.execute "update tag set user_id = ?, tag_name = ? where tag_id = ?", params
        } catch (ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.tagName)
            } else {
                throw new IllegalStateException(ex)
            }
        }
    }

    @Override
    void delete(int tagId) {
        sql.execute "delete from tag where tag_id = ?", [tagId]
    }

    @Override
    Optional<Tag> selectByTagId(int tagId) {
        def row = sql.firstRow "select tag_name, user_id from tag where tag_id = ?", [tagId]
        if (row == null) {
            return Optional.empty()
        }
        def tag = new Tag(tagId: tagId, tagName: row.tag_name, userId: row.user_id)
        return Optional.of(tag)
    }

    @Override
    List<Tag> selectAllForUser(int userId) {
        def rows = sql.rows "select tag_id, tag_name from tag where user_id = ?", [userId]
        rows.collect { new Tag(userId: userId, tagId: it.tag_id, tagName: it.tag_name) }
    }
}
